package cl.rivendel.servicios;

import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;

import cl.rivendel.modelo.Jugador;
import cl.rivendel.modelo.Mesa;
import cl.rivendel.modelo.Resultado;
import cl.rivendel.modelo.Ronda;

public class Services {

	/**
	 * crea la siguente ronda tomando en cuenta el resultado de la anterior Se
	 * ordena los match en rondas suizas, los mejores contra los mejores
	 * 
	 * @param p_ronda
	 */
	public Ronda calculaRondas(Ronda p_ronda) {

		Ronda ronda = null;

		if (p_ronda != null) {

			ronda = new Ronda();
			int numeroRonda = p_ronda.getNumeroRonda().intValue();

			numeroRonda++;
			ronda.setNumeroRonda(numeroRonda);

			List<Jugador> jugadores = p_ronda.getJugadores();

			if (jugadores != null && jugadores.size() > 0) {

				List<Mesa> mesas = crearMesasXPuntaje(jugadores);

				ronda.setMesas(mesas);

			}

		}

		return ronda;

	}

	/**
	 * Crea el listado de nuevas mesas
	 * 
	 * @param jugadores
	 * @return
	 */

	private List<Mesa> crearMesasXPuntaje(List<Jugador> jugadores) {

		// ordena jugadores por puntaje

		printOrdenJugadores(jugadores);
		Collections.sort(jugadores, new Comparator<Jugador>() {

			@Override
			public int compare(Jugador o1, Jugador o2) {

				// se comparan resultados
				Integer resultadoO1 = 0;
				Integer resultadoO2 = 0;

				resultadoO1 = calcularPuntajeJugador(o1);

				resultadoO2 = calcularPuntajeJugador(o2);

				return resultadoO2.compareTo(resultadoO1);
			}

			private Integer calcularPuntajeJugador(Jugador o1) {

				List<Resultado> resultados = o1.getResultados();

				int total = 0;

				for (Resultado resultado : resultados) {
					total = total + resultado.getPuntos().intValue();
				}

				return new Integer(total);
			}

		});
		printOrdenJugadores(jugadores);

		List<Mesa> mesas = crearMesas(jugadores);

		return mesas;
	}

	private void printOrdenJugadores(List<Jugador> jugadores) {

		if (jugadores != null) {

			StringBuffer buf = new StringBuffer();
			for (Jugador jugador : jugadores) {

				buf.append("Nombre: " + jugador.getNombre() + ", ");

				buf.append("puntaje: " + calcularPuntajeJugador(jugador));

				buf.append(System.getProperty("line.separator"));

			}
			System.out.println(buf.toString());
		}

	}

	private Integer calcularPuntajeJugador(Jugador o1) {

		List<Resultado> resultados = o1.getResultados();

		int total = 0;

		for (Resultado resultado : resultados) {
			total = total + resultado.getPuntos().intValue();
		}

		return new Integer(total);
	}

	public Ronda calculaRondas(List<Jugador> p_listaJugadores) {

		Ronda ronda;
		ronda = sorteoPrimeraRonda(p_listaJugadores);

		return ronda;
	}

	private Ronda sorteoPrimeraRonda(List<Jugador> jugadores) {

		Collections.shuffle(jugadores);

		Ronda ronda = new Ronda();

		List<Mesa> mesas = crearMesas(jugadores);

		ronda.setNumeroRonda(new Integer(1));

		ronda.setMesas(mesas);

		// calcular el total de jugadores

		return ronda;
	}

	private List<Mesa> crearMesas(List<Jugador> jugadores) {

		int numeroJugadores = jugadores.size();
		Mesa mesa;
		List<Mesa> mesas = new LinkedList<Mesa>();
		switch (numeroJugadores) {
		case 0:
			// no es posible crear ronda!!

			break;
		case 1:
			// no es posible crear ronda!!

			break;
		case 2:
			// no es posible crear ronda!!

			break;
		case 3:

			// solo se crea una mesa :S
			mesa = new Mesa();
			mesa.setJugadores(jugadores);
			mesa.setNumeroMesa(new Integer(0));

			break;

		case 4:

			// solo se crea una mesa :S
			mesa = new Mesa();
			mesa.setJugadores(jugadores);
			mesa.setNumeroMesa(new Integer(0));

			break;

		default:

			int totalMesas = numeroJugadores / 3;
			int sobras = numeroJugadores % 3;
			int numeroElemento = 0;
			List<Jugador> jugadoresMesa;

			for (int i = 0; i < totalMesas; i++) {
				mesa = new Mesa();
				mesa.setNumeroMesa(new Integer(i));
				jugadoresMesa = new LinkedList<Jugador>();
				mesa.setJugadores(jugadoresMesa);

				for (int j = 0; j < 3; j++) {

					Jugador jugador = jugadores.get(numeroElemento);
					jugadoresMesa.add(jugador);
					numeroElemento++;

				}

				mesas.add(mesa);

			}

			// se reparten los sobrantes
			if (sobras > 0) {

				for (int i = 0; i < totalMesas; i++) {
					mesa = mesas.get(i);

					jugadoresMesa = mesa.getJugadores();

					Jugador jugador = jugadores.get(numeroElemento);
					jugadoresMesa.add(jugador);
					numeroElemento++;
					if (numeroElemento == numeroJugadores) {
						break;
					}

				}

			}

			break;
		}

		return mesas;
	}

}
